package com.herui.sdyu_lib.blu.utils;

import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothProfile;
import android.content.Context;
import android.content.Intent;


import com.herui.sdyu_lib.blu.BlueDevice;
import com.herui.sdyu_lib.blu.BluDeviceConfig;
import com.herui.sdyu_lib.utils.ByteBuffUtils;
import com.herui.sdyu_lib.utils.LogUtils;
import com.herui.sdyu_lib.utils.ble.GattAppService;

import java.nio.ByteBuffer;
import java.util.Timer;
import java.util.TimerTask;
import java.util.UUID;


/**
 * Created by amanda.shan on 2017/8/15.
 */

public class BleService implements GattAppService.BleLister, BAction {

    // 蓝牙4.0
    private GattAppService mService;

    private UUID serviceUuid;
    private UUID readUuid;
    private UUID writeUuid;

    private ByteBuffer cacheBytes;

    private int mostWaitTime = 60 * 1000;
    private long reciveTime;
    private Timer detectTimeOutTimer;
    private Timer connectTimeOutTimer;

    private boolean connect = false;
    private boolean mNotify = false;
    private boolean mIndicate = false;
    private int reconnect = 0;

    private BluetoothGattCharacteristic mCharacteristic;

    private Blis blis;
    private int connectState = BluDeviceConfig.NOTCONNECT;

    public BleService(Blis blis, Context context) {
        this.blis = blis;

        mService = new GattAppService(this, context);
        mService.init();

        cacheBytes = ByteBuffer.allocate(7000);
        cacheBytes.flip();
    }

    public void setMostWaitTime(int mostWaitTime) {
        this.mostWaitTime = mostWaitTime;
    }

    public void setBlis(Blis blis) {
        this.blis = blis;
    }

    /**
     * 连接超时检测
     *
     * @param enable
     */
    private void connectTimeOut(boolean enable) {

        if (enable) {
            if (connectTimeOutTimer != null) {
                connectTimeOutTimer.cancel();
                connectTimeOutTimer = null;
            }

            if (connectTimeOutTimer == null) {
                connectTimeOutTimer = new Timer();
                connectTimeOutTimer.schedule(new TimerTask() {
                    @Override
                    public void run() {
                        if (connectState == BluDeviceConfig.CONNECTING) {
                            LogUtils.e("蓝牙4.0连接超时");
                            disConnect();
                            setState(BluDeviceConfig.NOTCONNECT);
                            connectTimeOutTimer = null;
                        }
                    }
                }, 6000);
            }
        } else {
            if (connectTimeOutTimer != null) {
                connectTimeOutTimer.cancel();
                connectTimeOutTimer = null;
            }
        }
    }

    /**
     * 超时检测定时器
     */
    private void detectionReviceTimeOut() {

        if (detectTimeOutTimer != null)
            detectTimeOutTimer.cancel();

        detectTimeOutTimer = new Timer();
        reciveTime = System.currentTimeMillis();
        detectTimeOutTimer.schedule(new TimerTask() {
            @Override
            public void run() {
                if (System.currentTimeMillis() - reciveTime > mostWaitTime) {
                    LogUtils.e("蓝牙4.0超时接收");
                    disConnect();
                    setState(BluDeviceConfig.NOTCONNECT);
                }
            }
        }, 1000, 1000);
    }

    @Override
    public void reciveBleMessage(Intent intent) {
        if (intent.getAction().equals(GattAppService.GATT_CONNECTION_STATE)) {
            connect = intent.getBooleanExtra(GattAppService.EXTRA_CONNECTED, false);
            int state = intent.getIntExtra(GattAppService.EXTRA_STATUS, BluetoothProfile
                    .STATE_DISCONNECTED);
            if (connect) {
                LogUtils.d("当前蓝牙4.0设备已经连接");
                setState(BluDeviceConfig.ISCONNECT);
            } else {
                if (state == BluetoothProfile.STATE_DISCONNECTED) {
                    disConnect();
                    setState(BluDeviceConfig.NOTCONNECT);
                    LogUtils.e("当前蓝牙4.0设备无法连接");
                } else if (state == BluetoothProfile.STATE_CONNECTING)
                    setState(BluDeviceConfig.CONNECTING);
            }
            connectTimeOut(false);

        } else if (intent.getAction().equals(GattAppService.GATT_SERVICES_REFRESHED)) {

            mCharacteristic = mService.getCharacteristic(serviceUuid, readUuid);
            if (mCharacteristic != null) {
                if ((mCharacteristic.getProperties() & BluetoothGattCharacteristic
                        .PROPERTY_READ) != 0) {
                    mService.readCharacteristic(mCharacteristic);

                    LogUtils.d("readCharacteristic");
                }

                if ((mCharacteristic.getProperties() & BluetoothGattCharacteristic
                        .PROPERTY_NOTIFY) != 0) {
                    setNotify(true);
                    LogUtils.d("setNotify");

                } else if ((mCharacteristic.getProperties() & BluetoothGattCharacteristic
                        .PROPERTY_INDICATE) != 0) {
                    setIndicate(true);
                    LogUtils.d("setIndicate");
                }
            }
        } else if (intent.getAction().equals(GattAppService.GATT_CHARACTERISTIC_READ)) {
            final byte[] value = intent.getByteArrayExtra(GattAppService.EXTRA_VALUE);

//            LogUtils.d("onCharacteristicRead：");
            if (value != null && value.length > 0) {
                reciveTime = System.currentTimeMillis();

                final StringBuilder stringBuilder = new StringBuilder(value.length);
                for (byte byteChar : value)
                    stringBuilder.append(String.format("%02X ", byteChar));

//                LogUtils.d("接收：" + stringBuilder.toString());
                if (blis != null) {
                    blis.reciveBlu(value, value.length);
                }
            }
        }
    }

    @Override
    public void sendOK(int size) {
        sendCache();
    }

    @Override
    public void sendFail() {
        sendCache();
    }

    private void sendCache() {
        BluetoothGattCharacteristic characteristic = mService.getCharacteristic
                (serviceUuid, writeUuid);
        if (characteristic == null) {
            LogUtils.e("send data characteristic == null writeUuid:" + writeUuid.toString());
//            LogUtils.e("蓝牙4.0 发送数据异常");
//            disConnect();
//            setState(DeviceConfig.NOTCONNECT);
            return;
        }

        byte[] send;
        if (ByteBuffUtils.getSize(cacheBytes) >= 20) {
            send = ByteBuffUtils.getBytes(cacheBytes, 20);
        } else if (ByteBuffUtils.getSize(cacheBytes) > 0)
            send = ByteBuffUtils.getBytes(cacheBytes, ByteBuffUtils.getSize(cacheBytes));
        else
            return;
        LogUtils.d("send size= " + send.length);
        StringBuilder builder = new StringBuilder();
        for (int i = 0; i < send.length; ++i) {
            builder.append(String.format("%x ", send[i]));
        }
        LogUtils.d("发送: " + builder.toString());
        characteristic.setValue(send);
        mService.writeCharacteristic(characteristic);
    }

    private void setNotify(boolean enable) {
        if (connect && mService != null && mCharacteristic != null) {
            mNotify = enable;
            mService.enableNotification(true, mCharacteristic);
        } else {
            mNotify = false;
        }
    }

    private void setIndicate(boolean enable) {
        if (connect && mService != null && mCharacteristic != null) {
            mIndicate = enable;
            mService.enableIndication(mIndicate, mCharacteristic);
        } else {
            mIndicate = false;
        }
    }

    private void setState(int connectState) {
        this.connectState = connectState;
        if (connectState == BluDeviceConfig.ISCONNECT)
            detectionReviceTimeOut();

        if (blis != null)
            blis.bluConenctState(connectState);
    }

    /**
     * 关闭所有
     */
    private void cancellAllConnect() {
        if (mService != null) {
            mService.disconnect();
            mService.close();
        }

        if (detectTimeOutTimer != null)
            detectTimeOutTimer.cancel();
        detectTimeOutTimer = null;
    }

    @Override
    public void send(byte[] bytes) {
        send(bytes, bytes.length);
    }

    @Override
    public void send(byte[] bytes, int len) {

        ByteBuffUtils.addBytes(cacheBytes, bytes, len);

        LogUtils.d("蓝牙4.0发送缓存添加数据量大小:" + len);
        LogUtils.d("蓝牙4.0发送缓存数据量大小:" + ByteBuffUtils.getSize(cacheBytes));
        sendCache();
    }

    @Override
    public void connect(BlueDevice blueDevice) {
        serviceUuid = blueDevice.getServiceUuid();
        readUuid = blueDevice.getReadUuid();
        writeUuid = blueDevice.getWriteUuid();

        setState(BluDeviceConfig.CONNECTING);
        reconnect = 0;

        connectTimeOut(true);
        mService.connect(blueDevice.getBlueMac());
    }

    @Override
    public void disConnect() {
        cancellAllConnect();
    }
}
